/*
 * @Author: xiaosihan
 * @Date: 2024-08-07 11:39:34
 * @Last Modified by: xiaosihan
 * @Last Modified time: 2025-10-02 14:26:46
 */

import dayjs from "dayjs";
import express from "express";
import { debounce, get } from "lodash";
import { Op, Sequelize } from "sequelize";
import tinify from "tinify";
import database from "../database";
import ServiceBase from "./ServiceBase";

// tinypng 相关服务
class TinypngService extends ServiceBase {
    constructor() {
        super();
    }
    
    // 获取接口响应测试数据
    get_api_response_test = async (
        req: express.Request,
        res: express.Response,
        next: express.NextFunction
    ) => {
        try {
            const data = await database.apiResponseTest.findAll({
                order: [["interval_time", "ASC"]]
            });
            this.success(res, data);
        } catch (error) {
            this.error(res, `获取接口响应测试数据失败: ${error}`);
        }
    };
    
    // 保存接口响应测试数据
    save_api_response_test_verify = this.paramNotEmpty(["interval_time", "response_time"]);
    save_api_response_test = async (
        req: express.Request,
        res: express.Response,
        next: express.NextFunction
    ) => {
        try {
            const { interval_time, response_time } = this.getParame(req);
            
            // 检查是否已存在该间隔时间的数据
            const existingData = await database.apiResponseTest.findOne({
                where: { interval_time: Number(interval_time) }
            });
            
            if (existingData) {
                // 如果存在，更新数据
                await database.apiResponseTest.update(
                    { response_time: Number(response_time) },
                    { where: { interval_time: Number(interval_time) } }
                );
            } else {
                // 如果不存在，创建新数据
                await database.apiResponseTest.create({
                    interval_time: Number(interval_time),
                    response_time: Number(response_time)
                });
            }
            
            this.success(res, {}, "保存成功");
        } catch (error) {
            this.error(res, `保存接口响应测试数据失败: ${error}`);
        }
    };

    // 清空接口响应测试数据
    clear_api_response_test = async (
        req: express.Request,
        res: express.Response,
        next: express.NextFunction
    ) => {
        try {
            await database.apiResponseTest.destroy({
                truncate: true // 清空表数据但保留表结构
            });
            this.success(res, {}, "清空成功");
        } catch (error) {
            this.error(res, `清空接口响应测试数据失败: ${error}`);
        }
    };

    // 分页获取key列表
    async _get_key_list(page: number, pageSize: number) {

        // 年月不是当前时就重置数据
        await database.keys.update(
            {
                month: dayjs().month() + 1,
                year: dayjs().year(),
                compressionCount: 0,
                residue: 500,
            },
            {
                where: {
                    [Op.or]: [ // 关键点：使用 Op.or 包裹数组
                        { month: { [Op.ne]: dayjs().month() + 1 } },// 条件2：month 不等于 当月
                        { year: { [Op.ne]: dayjs().year() } } // 条件3：year ≠ 当前年份
                    ]
                },
            }
        );

        const offset = (page - 1) * pageSize;
        const [list, total, { sumResidue, sumCompressionCount }] =
            await Promise.all([
                database.keys.findAll({
                    limit: Number(pageSize),
                    offset: offset,
                    where: { disable: 0 },
                    order: [
                        ["compressionCount", "DESC"], // 指定按照字段 residue 降序排列
                    ],
                }),
                database.keys.count({
                    where: { disable: 0 },
                }),
                database.keys
                    .findAll({
                        attributes: [
                            [Sequelize.fn("SUM", Sequelize.col("residue")), "sumResidue"],
                            [
                                Sequelize.fn("SUM", Sequelize.col("compressionCount")),
                                "sumCompressionCount",
                            ],
                        ],
                    })
                    .then((res) => {
                        const sumResidue =
                            Number(get(res, [0, "dataValues", "sumResidue"])) || 0;
                        const sumCompressionCount =
                            Number(get(res, [0, "dataValues", "sumCompressionCount"])) || 0;
                        return { sumResidue, sumCompressionCount };
                    }),
            ]);
        return { list, total, sumResidue, sumCompressionCount };
    }

    //分页获取key
    get_key_list_verify = this.paramNotEmpty(["page", "pageSize"]);
    get_key_list = async (
        req: express.Request,
        res: express.Response,
        next: express.NextFunction
    ) => {
        const { page, pageSize } = this.getParame(req);

        const { list, total, sumResidue, sumCompressionCount } =
            await this._get_key_list(page, pageSize);

        this.success(res, {
            list, // 当前页的列表
            total, // 数据总数
            sumResidue, // 已用总数
            sumCompressionCount, // 未用总数
        });
    };

    //添加key
    add_key_verify = this.paramNotEmpty(["key", "page", "pageSize"]);
    add_key = async (
        req: express.Request,
        res: express.Response,
        next: express.NextFunction
    ) => {
        const { key, page, pageSize } = this.getParame(req);

        // 检查是否有同名key
        const existingRecord = await database.keys.findOne({
            where: { ting_png_key: key },
        });

        if (existingRecord) {
            this.error(res, "有相同的key了");
            return;
        }

        //验证key是否有效
        const verif = await new Promise<boolean>(async (resolve, reject) => {
            try {
                tinify.key = key;
                await tinify.validate();
                resolve(true);
            } catch (error) {
                resolve(false);
            }
        });

        if (verif) {
            const year = dayjs().year();
            const month = dayjs().month() + 1;
            // const addResult =
            await database.keys.create({
                ting_png_key: key,
                compressionCount: tinify.compressionCount,
                year,
                month,
            });
            // console.log("addResult.dataValues", addResult.dataValues);
            // I7hDO2OgJ89OMBLrEqjCCiGZFrHsy1Fh
            // g5rrMCW88c4ZmWwBtYR4vryGHFkW1TPr
        } else {
            this.error(res, "无效的key");
            return;
        }

        const { list, total, sumResidue, sumCompressionCount } =
            await this._get_key_list(page, pageSize);

        this.success(res, {
            list, // 当前页的列表
            total, // 数据总数
            sumResidue, // 已用总数
            sumCompressionCount, // 未用总数
        });
    };

    //删除key 未实现
    del_key_verify = this.paramNotEmpty(["key", "page", "pageSize"]);
    del_key = async (
        req: express.Request,
        res: express.Response,
        next: express.NextFunction
    ) => {
        const { key, page, pageSize } = this.getParame(req);

        const { list, total, sumResidue, sumCompressionCount } =
            await this._get_key_list(page, pageSize);

        this.success(res, {
            list, // 当前页的列表
            total, // 数据总数
            sumResidue, // 已用总数
            sumCompressionCount, // 未用总数
        });
    };

    //更具需要的数量获取一个key
    get_key_by_conut_verify = this.paramNotEmpty(["conut"]);
    get_key_by_conut = async (
        req: express.Request,
        res: express.Response,
        next: express.NextFunction
    ) => {

        // 年月不是当前时就重置数据
        await database.keys.update(
            {
                month: dayjs().month() + 1,
                year: dayjs().year(),
                compressionCount: 0,
                residue: 500,
            },
            {
                where: {
                    [Op.or]: [ // 关键点：使用 Op.or 包裹数组
                        { month: { [Op.ne]: dayjs().month() + 1 } },// 条件2：month 不等于 当月
                        { year: { [Op.ne]: dayjs().year() } } // 条件3：year ≠ 当前年份
                    ]
                },
            }
        );

        const { conut } = this.getParame(req);

        const result = await database.keys.findOne({
            where: {
                residue: {
                    [Op.gte]: conut, // 小于 等于 conut
                },
            },
            order: [
                ["compressionCount", "DESC"], // 指定按照字段 compressionCount 降序排列
            ],
        });
        const id = get(result, ["dataValues", "id"]);
        const ting_png_key = get(result, ["dataValues", "ting_png_key"]);

        this.success(res, {
            id,
            ting_png_key,
        });

        // 更新 residue 字段，减少 conut
        database.keys.update(
            {
                residue: Sequelize.literal(`residue - ${conut}`),
                compressionCount: Sequelize.literal(`compressionCount + ${conut}`),
            }, // 使用 Sequelize.literal 来执行原始 SQL 操作
            { where: { ting_png_key } } // 指定更新条件
        );

        // 开始校验所有的key
        this.self_validate_all_key(req, res, next);
    };

    // 校验所有的key值
    validate_all_key = async (
        req: express.Request,
        res: express.Response,
        next: express.NextFunction
    ) => {

        const allKey = await database.keys.findAll({
            // where: {
            //     [Op.or]: [ // 关键点：使用 Op.or 包裹数组
            //         { compressionCount: { [Op.gt]: 0 } }, // 条件1：compressionCount 大于 0
            //         { month: { [Op.ne]: dayjs().month() + 1 } },// 条件2：month 不等于 当月
            //         { year: { [Op.ne]: dayjs().year() } } // 条件3：year ≠ 当前年份
            //     ]
            // },
        });
        for (let i = 0; i < allKey.length; i++) {
            const key = allKey[i].dataValues.ting_png_key;
            try {
                tinify.key = key;
                await tinify.validate();
                await database.keys.update(
                    {
                        month: dayjs().month() + 1,
                        year: dayjs().year(),
                        compressionCount: tinify.compressionCount || 0,
                        residue: 500 - (tinify.compressionCount || 0),
                    },
                    {
                        where: {
                            ting_png_key: key,
                        },
                    }
                );
            } catch (error) {
                console.log("校验失败", error);
            }
        }

        this.success(res, {}, "校验完成");
    };
    //校验
    self_validate_all_key = debounce(
        async (
            req: express.Request,
            res: express.Response,
            next: express.NextFunction
        ) => {
            console.log("开始校验");
            await this.validate_all_key(req, res, next);
            console.log("校验完成");
        },
        1000 * 60 * 10
    );

    // 更新余额和压缩次数
    update_residue_verify = this.paramNotEmpty(["key", "compressionCount", "residue"]);
    update_residue = async (
        req: express.Request,
        res: express.Response,
        next: express.NextFunction
    ) => {
        const { key, compressionCount, residue } = this.getParame(req);

        try {
            // 通过 key 更新 compressionCount 和 residue
            await database.keys.update(
                {
                    compressionCount: Number(compressionCount),
                    residue: Number(residue)
                },
                {
                    where: {
                        ting_png_key: key,
                        is_del: 0
                    }
                }
            );

            this.success(res, {}, "更新成功");
        } catch (error) {
            console.error("更新失败", error);
            this.error(res, "更新失败");
        }
    };
}

const tinypngService = new TinypngService();

export default tinypngService;
